#include <linux/utsname.h>
#include "socs/comm/types.h"
#include "socs/comm/config.h"
#include "socs/comm/constants.h"
#include "socs/mod/addr_opt.h"

struct  socs_config_t socs_config;
DEFINE_SPINLOCK(config_lock);

int config_init(const char *csDomain, const char *hostname,
				unsigned int tmHello, unsigned int tmDead, unsigned int tmStable,
				const char *mcIP4, const char *mcIP6)
{
	int ret;
//	log_debug("config_init hostname %s ,len %lu",hostname,strlen(hostname));
	spin_lock_bh(&config_lock);

	if (!csDomain) {
		log_warning("the csDomain is NULL,so we get default value");
		strcpy(socs_config.csDomain, CSDOMAIN_DEF);
	} else if (strlen(csDomain) > CSSIZE - 1) {
		log_warning("the csDomain too long ,max len of csDomain is %d,so we get default value",
					CSSIZE - 1);
		strcpy(socs_config.csDomain, CSDOMAIN_DEF);
	} else {
		strcpy(socs_config.csDomain, csDomain);
	}

	//strcpy(socs_config.csDomain,CSDOMAIN_DEF);

	if (!hostname) {
		log_warning("the hostname is NULL,so we get default value");
		strcpy(socs_config.hostname, utsname()->nodename);
	} else if (strlen(hostname) > HOSTNAMESIZE) {
		log_warning("the hostname too long ,max len of hostname is %d,so we get default value",
					HOSTNAMESIZE);
		strcpy(socs_config.hostname, utsname()->nodename);
	} else {
		strcpy(socs_config.hostname, hostname);
	}

	if (tmHello > 0) {
		socs_config.tmHello = tmHello;
	} else {
		socs_config.tmHello = TMHELLO_DEF;
	}

	if (tmDead > 0) {
		socs_config.tmDead = tmDead;
	} else {
		socs_config.tmDead = TMDEAD_DEF;
	}

	if (tmStable > 0) {
		socs_config.tmStable = tmStable;
	} else {
		socs_config.tmStable = TMSTABLE_DEF;
	}

//	socs_config.sap_vote=0;
	if (!mcIP6) {
		ret = str_to_addr6(MCIP6_DEF, &socs_config.mcIP6);

		if (ret < 0) {
			log_warning("MCIP6_DEF to socs_config.mcIP6 failed");
		}
	} else {
		ret = str_to_addr6(mcIP6, &socs_config.mcIP6);

		if (ret < 0) {
			log_warning("mcIP6 to socs_config.mcIP6 failed");
		}
	}

	if (!mcIP4) {
		ret = str_to_addr4(MCIP4_DEF, &socs_config.mcIP4);

		if (ret < 0) {
			log_warning("MCIP4_DEF to socs_config.mcIP6 failed");
		}
	} else {
		ret = str_to_addr4(mcIP4, &socs_config.mcIP4);

		if (ret < 0) {
			log_warning("mcIP4 to socs_config.mcIP6 failed");
		}
	}

	//ret=str_to_addr4(MCIP4_DEF,&socs_config.mcIP4);
	spin_unlock_bh(&config_lock);
	log_info("socs_config:csDomain=%s,hostname=%s,tmHello=%d,tmDead=%d,tmStable=%d,mcIP6=%pI6c,mcIP4=%pI4",
			 socs_config.csDomain, socs_config.hostname, socs_config.tmHello,
			 socs_config.tmDead,
			 socs_config.tmStable, &socs_config.mcIP6, &socs_config.mcIP4);
	return ret;
}
void config_destroy(void)
{
}
int  config_update_csDomain(const char *csdomain)
{
	spin_lock_bh(&config_lock);

	if (strlen(csdomain) > CSSIZE - 1) {
		spin_unlock_bh(&config_lock);
		log_warning("csdomain is to long ");
		return -1;
	}

	memset(&socs_config.csDomain, 0, CSSIZE);
	strcpy(socs_config.csDomain, csdomain);
	spin_unlock_bh(&config_lock);
	log_debug("config_update_csDomain:%s", socs_config.csDomain);
	return 0;
}
int  config_update_hostname(const char *hostname)
{
	spin_lock_bh(&config_lock);

	if (strlen(hostname) > HOSTNAMESIZE - 1) {
		spin_unlock_bh(&config_lock);
		log_warning("hostname is to long ");
		return -1;
	}

	memset(&socs_config.hostname, 0, HOSTNAMESIZE);
	strcpy(socs_config.hostname, hostname);
	spin_unlock_bh(&config_lock);
	log_debug("config_update_hostname:%s", socs_config.hostname);
	return 0;
}
int  config_update_tmHello(unsigned int tmhello)
{
	spin_lock_bh(&config_lock);
	memset(&socs_config.tmHello, 0, sizeof(unsigned int));
	socs_config.tmHello = tmhello;
	spin_unlock_bh(&config_lock);
	log_debug("config_update_tmHello:%u", socs_config.tmHello);
	return 0;
}
int  config_update_tmDead(unsigned int tmdead)
{
	spin_lock_bh(&config_lock);
	memset(&socs_config.tmDead, 0, sizeof(unsigned int));
	socs_config.tmDead = tmdead;
	spin_unlock_bh(&config_lock);
	log_debug("config_update_tmDead:%u", socs_config.tmDead);
	return 0;
}
int  config_update_tmStable(unsigned int tmstable)
{
	spin_lock_bh(&config_lock);
	memset(&socs_config.tmStable, 0, sizeof(unsigned int));
	socs_config.tmStable = tmstable;
	spin_unlock_bh(&config_lock);
	log_debug("config_update_tmStable:%u", socs_config.tmStable);
	return 0;
}
int config_update_mcIP4(struct in_addr mcip4)
{
	spin_lock_bh(&config_lock);
	socs_config.mcIP4 = mcip4;
	spin_unlock_bh(&config_lock);
	log_debug("config_update_mcIP4:%pI4", &socs_config.mcIP4);
	return 0;
}
int config_update_mcIP6(struct in6_addr mcip6)
{
	spin_lock_bh(&config_lock);
	socs_config.mcIP6 = mcip6;
	spin_unlock_bh(&config_lock);
	log_debug("config_update_mcIP6:%pI6c", &socs_config.mcIP6);
	return 0;
}
int socs_config_get(int key, void *result)
{
	spin_lock_bh(&config_lock);

	switch (key) {
	case ARGP_CSDOMAIN:
		memcpy(result, socs_config.csDomain, CSSIZE);
		break;

	case ARGP_HOSTNAME:
		memcpy(result, socs_config.hostname, HOSTNAMESIZE);
		break;

	case ARGP_TMHELLO:
		(*(unsigned int *)result) = socs_config.tmHello;
		break;

	case ARGP_TMDEAD:
		(*(unsigned int *)result) = socs_config.tmDead;
		break;

	case ARGP_TMSTABLE:
		(*(unsigned int *)result) = socs_config.tmStable;
		break;

	case ARGP_MCIP4:
		memcpy(result, &socs_config.mcIP4, sizeof(struct in_addr));
		break;

	case ARGP_MCIP6:
		memcpy(result, &socs_config.mcIP6, sizeof(struct in6_addr));
		break;

	default:
		log_debug("undefined key,%d\n", key);
	}

	spin_unlock_bh(&config_lock);
	return 0;
}
